/*
 * BZPModel.cpp
 *
 *  Created on: 24/05/2014
 *      Author: javier
 */

#include "BZPModel.h"
#include <math.h>

BZPModel::BZPModel() {
	width = height = 0;
	idPlayer = 0;
}

Positionable* BZPModel::add(Positionable *p) {
	objects[p->getId()] = p;
	ModelObject mo = p->getModelObjectType();
	if (mo == BOX || mo == METAL) {
		solids[p->getId()] = p;
	}
	return p;
}

void BZPModel::remove(int id) {
	objects.erase(id);
	solids.erase(id);
}

void BZPModel::update(int id, double x, double y) {
	if (objects.count(id) > 0 && objects[id] != NULL) {
		objects[id]->setX(x);
		objects[id]->setY(y);
	}
}

std::pair<int, int> BZPModel::query(int id) {
	std::pair<int, int> pos;
	pos.first = -1;
	pos.second = -1;
	if (!objects[id]) {
		return pos;
	}
	if (objects.count(id) > 0) {
		pos.first = (int)objects[id]->getX() + 0.5f;
		pos.second = (int)objects[id]->getY() + 0.5f;
	}
	return pos;
}

void BZPModel::clear() {
	objects.clear();
	solids.clear();
}

void BZPModel::setIDTarget(int id) {
	this->idPlayer = id;
}

void BZPModel::setDimensions(int x, int y) {
	width = x;
	height = y;
}

Positionable* BZPModel::getTarget() {
	return objects[idPlayer];
}

int BZPModel::getIDTarget() {
	return idPlayer;
}

bool BZPModel::validate(EventToValidate event) {
	std::pair<int, int> pos = query(idPlayer);
	if (pos.first == -1 && pos.second == -1)
		return true;
	bool bounds = true;
	if (event == MOVE_UP) {
		bounds = pos.second > 0;
	} else if (event == MOVE_DOWN) {
		bounds = pos.second < height - 1;
	} else if (event == MOVE_LEFT) {
		bounds = pos.first > 0;
	} else { // event == MOVE_RIGHT
		bounds = pos.first < width - 1;
	}
	if (!bounds)
		return false;
	bool colide = false;
	std::map<int, Positionable*>::iterator iter;
	int xObject;
	int yObject;
	for (iter = solids.begin(); iter != solids.end(); ++iter) {
		xObject = (int)iter->second->getX() + 0.5f;
		yObject = (int)iter->second->getY() + 0.5f;
		bool near = (absoluteValue(xObject - pos.first) <= 1
				&& absoluteValue(yObject - pos.second) <= 1);
		if (!near)
			continue;
		if (event == MOVE_UP) {
			colide = (pos.second == yObject + 1 && pos.first == xObject);
		} else if (event == MOVE_DOWN) {
			colide = (yObject == pos.second + 1 && pos.first == xObject);
		} else if (event == MOVE_LEFT) {
			colide = (pos.first == xObject + 1 && pos.second == yObject);
		} else { // event == MOVE_RIGHT
			colide = (xObject == pos.first + 1 && pos.second == yObject);
		}
//		colide = (distance(xObject, yObject, pos.first, pos.second) < 1);
		if (colide)
			break;
	}
	if (colide)
		return false;
	return true;
}

BZPModel::~BZPModel() {
// TODO Auto-generated destructor stub
}

double BZPModel::absoluteValue(double val) {
	if (val < 0)
		return -val;
	return val;
}

double BZPModel::distance(double xObject, double yObject, double xPos,
		double yPos) {
	return sqrt(pow(xObject - xPos, 2.0) + pow(yObject - yPos, 2.0));
}

Positionable* BZPModel::getObject(int id) {
	return objects[id];
}
